using ILRuntime.CLR.Method;
using ILRuntime.Runtime.Enviorment;
using ILRuntime.Runtime.Intepreter;
using System;
using Gj.Galaxy.Logic;

namespace Gj.ILRuntimeExt.Adapt
{
    //这个类就是继承适配器类
    public class GameBeforeListenerAdaptor : CrossBindingAdaptor
    {
        public override Type BaseCLRType
        {
            get
            {
                //如果你是想一个类实现多个Unity主工程的接口，这里需要return null;
                return typeof(GameBeforeListener);//这是你想继承的那个类
//                return null;
            }
        }

        public override Type[] BaseCLRTypes
        {
            get
            {
                //跨域继承只能有1个Adapter，因此应该尽量避免一个类同时实现多个外部接口，
                //ILRuntime虽然支持同时实现多个接口，但是一定要小心这种用法，使用不当很容易造成不可预期的问题
                //日常开发如果需要实现多个DLL外部接口，请在Unity这边先做一个基类实现那些个接口，然后继承那个基类
                //如需一个Adapter实现多个接口，请用下面这行
//                return new Type[] { typeof(BaseUISystem), typeof(UISystem), typeof(GameBeforeListener) };
                return null;
            }
        }

        public override Type AdaptorType
        {
            get
            {
                return typeof(Adaptor);//这是实际的适配器类
            }
        }

        public override object CreateCLRInstance(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
        {
            return new Adaptor(appdomain, instance);//创建一个新的实例
        }

        //实际的适配器类需要继承你想继承的那个类，并且实现CrossBindingAdaptorType接口
        class Adaptor : GameBeforeListener, CrossBindingAdaptorType
        {
            ILTypeInstance instance;
            ILRuntime.Runtime.Enviorment.AppDomain appdomain;

            private IMethod mOnEnterRoom;
            private bool mOnEnterRoomGot;

            private IMethod mOnPlayerJoin;
            private bool mOnPlayerJoinGot;

            private IMethod mOnPlayerLeave;
            private bool mOnPlayerLeaveGot;

            private IMethod mOnPlayerRejoin;
            private bool mOnPlayerRejoinGot;

            private IMethod mOnProcessRoom;
            private bool mOnProcessRoomGot;
            
            private IMethod mOnFailConnect;
            private bool mOnFailConnectGot;
            
            bool isTestVirtualInvoking = false;
            //缓存这个数组来避免调用时的GC Alloc
            object[] param1 = new object[1];

            public Adaptor()
            {

            }

            public Adaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
            {
                this.appdomain = appdomain;
                this.instance = instance;
            }

            public ILTypeInstance ILInstance { get { return instance; } }

            public void OnEnterRoom(bool success)
            {
                if (!mOnEnterRoomGot)
                {
                    mOnEnterRoom = instance.Type.GetMethod("OnEnterRoom", 1);
                    mOnEnterRoomGot = true;
                }

                param1[0] = success;
                if (mOnEnterRoom != null)
                    appdomain.Invoke(mOnEnterRoom, instance, param1);
            }

            public void OnPlayerJoin(GamePlayer player)
            {
                if (!mOnPlayerJoinGot)
                {
                    mOnPlayerJoin = instance.Type.GetMethod("OnPlayerJoin", 1);
                    mOnPlayerJoinGot = true;
                }

                param1[0] = player;
                if (mOnPlayerJoin != null)
                    appdomain.Invoke(mOnPlayerJoin, instance, param1);
            }

            public void OnPlayerLeave(GamePlayer player)
            {
                if (!mOnPlayerLeaveGot)
                {
                    mOnPlayerLeave = instance.Type.GetMethod("OnPlayerLeave", 1);
                    mOnPlayerLeaveGot = true;
                }

                param1[0] = player;
                if (mOnPlayerLeave != null)
                    appdomain.Invoke(mOnPlayerLeave, instance, param1);
            }

            public void OnPlayerRejoin(GamePlayer player)
            {
                if (!mOnPlayerRejoinGot)
                {
                    mOnPlayerRejoin = instance.Type.GetMethod("OnPlayerRejoin", 1);
                    mOnPlayerRejoinGot = true;
                }

                param1[0] = player;
                if (mOnPlayerRejoin != null)
                    appdomain.Invoke(mOnPlayerRejoin, instance, param1);
            }

            public void OnFailConnect()
            {
                if (!mOnFailConnectGot)
                {
                    mOnFailConnect = instance.Type.GetMethod("OnFailConnect", 0);
                    mOnFailConnectGot = true;
                }

                if (mOnFailConnect != null)
                    appdomain.Invoke(mOnFailConnect, instance);
            }

            public void OnProcessRoom(object[] data)
            {
                if (!mOnProcessRoomGot)
                {
                    mOnProcessRoom = instance.Type.GetMethod("OnProcessRoom", 1);
                    mOnProcessRoomGot = true;
                }

                param1[0] = data;
                if (mOnProcessRoom != null)
                    appdomain.Invoke(mOnProcessRoom, instance, param1);
            }
        }
    }
}
